package net.wangds.jpa.ctrl;

import io.swagger.annotations.ApiOperation;
import net.wangds.data.DisableEnum;
import net.wangds.data.Disableable;
import net.wangds.data.RemovedEnum;
import net.wangds.data.WithId;
import net.wangds.jpa.Sorts;
import net.wangds.jpa.comp.AbstractRemovedComp;
import net.wangds.jpa.convertor.Page2MultipleRespConv;
import net.wangds.jpa.convertor.PagingForm2PageRequestConv;
import net.wangds.jpa.service.AbstractJpaService;
import net.wangds.web.entrypoint.BaseMultipleResp;
import net.wangds.web.entrypoint.BaseResp;
import net.wangds.web.entrypoint.PagingForm;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import java.util.Optional;

/**
 * 抽象的JPA服务控制器.
 * <p>通过JPA服务接口实现的基本数据操作.</p>
 *
 * @author 王东石 2020/11/11 16:33.
 */
@SuppressWarnings("unused")
public abstract class AbstractJpaServiceCtrl <T extends WithId<String>> {

    /**
     * 获得JPA服务实例.
     * @return 服务实例.
     */
    protected abstract AbstractJpaService<T, ? extends AbstractRemovedComp<T>> fetchService();

    /**
     * 将查询结果页转换为Http应答.
     */
    @Autowired
    protected Page2MultipleRespConv<T> mmConvPage2Resp;


    /**
     * 将分页查询请求转换为查询分页请求.
     */
    protected final PagingForm2PageRequestConv mmConvPf2Pr = new PagingForm2PageRequestConv(() -> Sorts.createTm_desc);

    @ApiOperation("根据Id查询")
    @RequestMapping(value = "/one/{id}", method = RequestMethod.GET)
    public ResponseEntity<BaseResp<T>> ById(
            @PathVariable("id") String id
    ){
        Optional<T> opt = fetchService().findById(id);
        return opt.map(t -> ResponseEntity.ok(BaseResp.of(t))).orElseGet(() -> ResponseEntity.notFound().build());
    }


    /**
     * 列出所有.
     * @return 查询结果.
     */
    @ApiOperation("列出所有")
    @RequestMapping(value="/all", method = RequestMethod.POST)
    public BaseMultipleResp<T> listAll(){
        return mmConvPage2Resp.convert(new PageImpl<>(fetchService().findAll(Sorts.createTm_desc)));
    }


    /**
     * 查询列表.
     * @param page 分页参数.
     * @return 查询结果.
     */
    @ApiOperation("查询列表")
    @RequestMapping(value="/list", method = RequestMethod.POST)
    public BaseMultipleResp<T> list(
            @RequestBody PagingForm page){
        String keywords = page.getKeywords();
        PageRequest paging = mmConvPf2Pr.convert(page);
        AbstractJpaService<T, ? extends AbstractRemovedComp<T>> service = fetchService();
        if(StringUtils.isBlank(keywords)) {
            return mmConvPage2Resp.convert(service.findAll(paging));
        }else {
            return mmConvPage2Resp.convert(service.findAllWithKeywords(keywords, paging));
        }
    }

    /**
     * 保存或修改对象.
     * @param target 对象.
     * @return 保存结果.
     */
    @ApiOperation("保存或修改对象.")
    @RequestMapping(value = "/", method = RequestMethod.PUT)
    public ResponseEntity<BaseResp<T>> put(
            @RequestBody T target
    ){
        if(target.getRemoved()==null){
            target.setRemoved(RemovedEnum.NORMAL);
        }
        if(target instanceof Disableable){
            Disableable t = (Disableable) target;
            if(t.getDisable()==null){
                t.setDisable(DisableEnum.NORMAL);
            }
        }
        T res = fetchService().save(target);
        if(res!=null) {
            return ResponseEntity.ok(BaseResp.of(res));
        }else{
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(BaseResp.<T>of(null).code(-1).msg("保存失败"));
        }
    }

    /**
     * 根据唯一标识删除实体.
     * @param id 唯一标识.
     * @return 删除结果.
     */
    @ApiOperation("根据唯一标识删除实体")
    @RequestMapping(value = "/remove/{id}", method = RequestMethod.POST)
    public ResponseEntity<BaseResp<Boolean>> delete(
            @PathVariable("id") String id){
        fetchService().remove(id);
        return ResponseEntity.ok(BaseResp.of(true));
    }


}
